home *** CD-ROM | disk | FTP | other *** search
/ Qu.......ke Neue Level / KroGer Software GmbH - Qu_ke.iso / UTILITY / PRG8.ZIP / Q_MISC.C < prev    next >
C/C++ Source or Header  |  1996-03-02  |  10KB  |  476 lines

  1. /*
  2.  * Copyright (C) 1996 by Raphael Quinet.  All rights reserved.
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and
  5.  * its documentation for any purpose and without fee is hereby
  6.  * granted, provided that the above copyright notice appear in all
  7.  * copies and that both that copyright notice and this permission
  8.  * notice appear in supporting documentation.  If more than a few
  9.  * lines of this code are used in a program which displays a copyright
  10.  * notice or credit notice, the following acknowledgment must also be
  11.  * displayed on the same screen: "This product includes software
  12.  * developed by Raphael Quinet for use in the Quake Editing Utilities
  13.  * project."  THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT EXPRESS OR
  14.  * IMPLIED WARRANTY.
  15.  *
  16.  * More information about the QEU project can be found on the WWW:
  17.  * "http://www.montefiore.ulg.ac.be/~quinet/games/editing.html" or by
  18.  * mail: Raphael Quinet, 9 rue des Martyrs, B-4550 Nandrin, Belgium.
  19.  */
  20.  
  21. /*
  22.  * Q_MISC.C - Error logs, memory management, selection of objects, etc.
  23.  *
  24.  * This file was derived from D_MISC.C (Doom Editing Utilities 5.3),
  25.  * written by the DEU Team: Raphael Quinet, Brandon Wyber, Ted
  26.  * Vessenes and others.
  27.  */
  28.  
  29. /* the includes */
  30. #include "qeu.h"
  31. #ifdef QEU_UNIX
  32. #include <sys/types.h>
  33. #include <sys/time.h>
  34. #else
  35. #include <dos.h>
  36. #include <time.h>
  37. #endif
  38. #if defined (__TURBOC__)
  39. #include <alloc.h>
  40. #elif defined(__GO32__)
  41. #include <pc.h>
  42. #endif
  43. #include "q_misc.h"
  44.  
  45. /*! Dirty hack while the config stuff is not available */
  46. struct 
  47. {
  48.   Bool debug;
  49. } Config;
  50.  
  51. /* global variable */
  52. FILE  *logfile = NULL;           /* file pointer to the error log */
  53.  
  54.  
  55. /*
  56.  * Wait for a specified number of milliseconds.
  57.  */
  58. void MSleep(int msec)
  59. {
  60. #ifdef QEU_UNIX
  61.   struct timeval tv;
  62.  
  63.   tv.tv_sec  = msec / 1000;
  64.   tv.tv_usec = 1000 * (msec % 1000);
  65.   (void) select(0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv);
  66. #else
  67.   delay(msec);
  68. #endif
  69. }
  70.  
  71.  
  72. /*
  73.  * Report a non-fatal error.
  74.  */
  75. void ProgWarning(char *errstr, ...)
  76. {
  77.   va_list args;
  78.  
  79.   va_start(args, errstr);
  80.   printf("\nWarning: ");
  81.   vprintf(errstr, args);
  82.   printf("\n");
  83.   if (Config.debug == TRUE && logfile != NULL)
  84.     {
  85.       fprintf(logfile, "\nWarning: *** ");
  86.       vfprintf(logfile, errstr, args);
  87.       fprintf(logfile, " ***\n");
  88.       fclose(logfile);
  89.     }
  90.   va_end(args);
  91.  
  92. }
  93.  
  94.  
  95. /*
  96.  * Terminate the program reporting an error.
  97.  */
  98. void ProgError(char *errstr, ...)
  99. {
  100.   va_list args;
  101.  
  102.   va_start(args, errstr);
  103.   printf("\nProgram Error: *** ");
  104.   vprintf(errstr, args);
  105.   printf(" ***\n");
  106.   if (Config.debug == TRUE && logfile != NULL)
  107.     {
  108.       fprintf(logfile, "\nProgram Error: *** ");
  109.       vfprintf(logfile, errstr, args);
  110.       fprintf(logfile, " ***\n");
  111.     }
  112.   va_end(args);
  113.   exit(5);
  114. }
  115.  
  116.  
  117. /*
  118.  * Write a message in the log file.
  119.  */
  120. void LogMessage(char *logstr, ...)
  121. {
  122.   va_list  args;
  123.   time_t   tval;
  124.   char    *tstr;
  125.  
  126.   if (Config.debug == TRUE && logfile != NULL)
  127.     {
  128.       va_start(args, logstr);
  129.       /* if the messsage begins with ":", output the current date & time first */
  130.       if (logstr[0] == ':')
  131.         {
  132.           time(&tval);
  133.           tstr = ctime(&tval);
  134.           tstr[strlen(tstr) - 1] = '\0';
  135.           fprintf(logfile, "%s", tstr);
  136.         }
  137.       vfprintf(logfile, logstr, args);
  138.       /* write the message immediately, in case something bad happens next */
  139.       fflush(logfile);
  140.       va_end(args);
  141.     }
  142. }
  143.  
  144.  
  145. /*
  146.  * Open the log file and write a first message in it.
  147.  */
  148. void OpenLogFile(char *logfilename)
  149. {
  150.   if (Config.debug == TRUE)
  151.     {
  152.       logfile = fopen(logfilename, "a");
  153.       if (logfile == NULL)
  154.         printf("Warning: Could not open log file \"%s\"", logfilename);
  155.       LogMessage(": Starting QEU %s\n", QEU_VERSION);
  156.     }
  157. }
  158.  
  159. /*
  160.  * Close the log file.
  161.  */
  162. void CloseLogFile(void)
  163. {
  164.   if (logfile != NULL)
  165.     {
  166.       LogMessage(": The end!\n\n\n");
  167.       fclose(logfile);
  168.     }
  169. }
  170.  
  171.  
  172. /*
  173.  * Test if an object is in the selection list.
  174.  */
  175. Bool IsSelected(SelPtr list, Int16 objnum)
  176. {
  177.   SelPtr cur;
  178.  
  179.   for (cur = list; cur; cur = cur->next)
  180.     if (cur->objnum == objnum)
  181.       return TRUE;
  182.   return FALSE;
  183. }
  184.  
  185.  
  186. /*
  187.  * Add an object to the selection list.
  188.  */
  189. void SelectObject(SelPtr *list, Int16 objnum)
  190. {
  191.   SelPtr cur;
  192.  
  193. #ifdef DEBUG
  194.   if (objnum < 0)
  195.     ProgError("BUG: SelectObject called with %d", objnum);
  196. #endif
  197.   cur = (SelPtr) QMalloc(sizeof(struct SelectionList));
  198.   cur->next = *list;
  199.   cur->objnum = objnum;
  200.   *list = cur;
  201. }
  202.  
  203.  
  204. /*
  205.  * Remove an object from the selection list.
  206.  */
  207. void UnSelectObject(SelPtr *list, Int16 objnum)
  208. {
  209.   SelPtr cur, prev;
  210.  
  211. #ifdef DEBUG
  212.   if (objnum < 0)
  213.     ProgError("BUG: UnSelectObject called with %d", objnum);
  214. #endif
  215.   prev = NULL;
  216.   cur = *list;
  217.   while (cur)
  218.     {
  219.       if (cur->objnum == objnum)
  220.         {
  221.           if (prev)
  222.             prev->next = cur->next;
  223.           else
  224.             *list = cur->next;
  225.           QFree(cur);
  226.           if (prev)
  227.             cur = prev->next;
  228.           else
  229.             cur = NULL;
  230.         }
  231.       else
  232.         {
  233.           prev = cur;
  234.           cur = cur->next;
  235.         }
  236.     }
  237. }
  238.  
  239.  
  240. /*
  241.  * Forget the selection list.
  242.  */
  243. void ForgetSelection(SelPtr *list)
  244. {
  245.   SelPtr cur, prev;
  246.   
  247.   cur = *list;
  248.   while (cur)
  249.     {
  250.       prev = cur;
  251.       cur = cur->next;
  252.       QFree(prev);
  253.     }
  254.   *list = NULL;
  255. }
  256.  
  257.  
  258. /*
  259.    Note from RQ:
  260.       In order to prevent memory fragmentation on large blocks (greater
  261.       than 1K), you can define MEMORY_LOWFRAG and the size of all blocks
  262.       will be rounded up to 8K.  Thus, "realloc" will move the block if
  263.       and only if it has grown or shrunk enough to cross a 8K boundary.
  264.       I don't do that for smaller blocks (smaller than 1K), because this
  265.       would waste too much space if these blocks were rounded up to 8K.
  266.       There are lots of "malloc"'s for very small strings (9 characters)
  267.       or filenames, etc.
  268.    Thanks to Craig Smith (bcs@cs.tamu.edu) for his ideas about memory
  269.       fragmentation.
  270. */
  271.  
  272. #ifdef MEMORY_LOWFRAG
  273. #define SIZE_THRESHOLD  1024
  274. #define SIZE_OF_BLOCK   4095  /* actually, this is (size - 1) */
  275. #endif
  276.  
  277.  
  278. /*
  279.  * Allocate memory with error checking.
  280.  */
  281. void huge *QMalloc(UInt32 size)
  282. {
  283.   void huge *ret;
  284.  
  285. #ifdef MEMORY_LOWFRAG
  286.   /* limit fragmentation on large blocks */
  287.   if (size >= (UInt32) SIZE_THRESHOLD)
  288.     size = (size + (UInt32) SIZE_OF_BLOCK) & ~((UInt32) SIZE_OF_BLOCK);
  289. #endif
  290. #ifdef __TURBOC__
  291.   ret = farmalloc(size);
  292. #else
  293.   ret = malloc(size);
  294. #endif
  295.   if (!ret)
  296.     ProgError("out of memory (cannot allocate %lu far bytes)", size);
  297.   return ret;
  298. }
  299.  
  300.  
  301. /*
  302.  * Reallocate memory with error checking.
  303.  */
  304. void huge *QRealloc(void huge *old, UInt32 size)
  305. {
  306.   void huge *ret;
  307.  
  308. #ifdef MEMORY_LOWFRAG
  309.   /* limit fragmentation on large blocks */
  310.   if (size >= (UInt32) SIZE_THRESHOLD)
  311.     size = (size + (UInt32) SIZE_OF_BLOCK) & ~((UInt32) SIZE_OF_BLOCK);
  312. #endif
  313. #ifdef __TURBOC__
  314.   ret = farrealloc(old, size);
  315. #else
  316.   ret = realloc(old, size);
  317. #endif
  318.   if (!ret)
  319.     ProgError("out of memory (cannot reallocate %lu far bytes)", size);
  320.   return ret;
  321. }
  322.  
  323.  
  324. /*
  325.  * Free memory.
  326.  */
  327. void QFree(void huge *ptr)
  328. {
  329.   /* just a wrapper around farfree(), but provide an entry point */
  330.   /* for memory debugging routines... */
  331. #ifdef __TURBOC__
  332.   farfree(ptr);
  333. #else
  334.   free(ptr);
  335. #endif
  336. }
  337.  
  338.  
  339. /*
  340.  * Duplicate an area of memory in a newly allocated location.
  341.  */
  342. UInt8 *QMemDup(UInt8 *src, UInt32 size)
  343. {
  344.   UInt8 *ret;
  345.   UInt8 *sp, *dp;
  346.  
  347.   if (src == NULL)
  348.     ProgError("BUG: cannot duplicate NULL pointer");
  349.   ret = (UInt8 *)QMalloc(size);
  350.   /* copy 32K blocks at a time, because old DOS doesn't like >64K blocks */
  351.   sp = src;
  352.   dp = ret;
  353.   while (size > 0x8000L)
  354.     {
  355.       memcpy(dp, sp, 0x8000);
  356.       sp = sp + 0x8000;
  357.       dp = dp + 0x8000;
  358.       size -= 0x8000;
  359.     }
  360.   if (size > 0)
  361.     memcpy(dp, sp, size);
  362.   return ret;
  363. }
  364.  
  365.  
  366. /*
  367.  * Duplicate a string in a newly allocated location, with error checking.
  368.  */
  369. char *QStrDup(char *src)
  370. {
  371.   char *ret;
  372.  
  373.   if (src == NULL)
  374.     ProgError("BUG: cannot duplicate NULL pointer");
  375.   ret = (char *)QMalloc(strlen(src) + 1);
  376.   return strcpy(ret, src);
  377. }
  378.  
  379.  
  380. /*
  381.  * Copy a string into another (like strncpy) and pad the destination string
  382.  * with zeroes.  The destination string will not be null-terminated if
  383.  * strlen(src) > n.
  384.  */
  385. char *QStrNCpy(char *dest, char *src, int n)
  386. {
  387.   int   i;
  388.   char *dp, *sp;
  389.  
  390.   dp = dest;
  391.   sp = src;
  392.   for (i = 0; *sp && i < n; i++)
  393.     *dp++ = *sp++;
  394.   for (; i < n; i++)
  395.     *dp++ = 0;
  396.   return dest;
  397. }
  398.  
  399.  
  400. /*
  401.  * Does something strange with a string...  :-)  Strips leading
  402.  * directory name from "src", removes the extension (anything that
  403.  * follows a dot '.'), converts the string to upper case and truncate
  404.  * it after "n" characters.  Useful for making a WAD or WAD2 entry
  405.  * name from a file name.
  406.  */
  407. char *QStrNDupHack(char *src, int n)
  408. {
  409.   int   i;
  410.   char *ret, *dp, *sp;
  411.  
  412.   if (src == NULL)
  413.     ProgError("BUG: cannot convert a NULL string to an entry name");
  414.   if (n <= 0)
  415.     ProgError("BUG: entry size must be greater than 0 (%d)", n);
  416.   sp = src;
  417.   for (dp = sp; *dp; dp++)
  418.     if (*dp == '/' || *dp == '\\')
  419.       sp = dp + 1;
  420.   ret = (char *)QMalloc(n);
  421.   dp = ret;
  422.   for (i = 0; *sp && *sp != '.' && i < n; i++)
  423.     *dp++ = (char)toupper((int)*sp++);
  424.   for (; i < n; i++)
  425.     *dp++ = 0;
  426.   return ret;
  427. }
  428.  
  429.  
  430. #ifndef QEU_DOS
  431. /*
  432.  * Convert a string to upper case, overwriting its space.
  433.  */
  434.  
  435. char *strupr(char *s)
  436. {
  437.   char *cp;
  438.  
  439.   if (s == NULL)
  440.     ProgError("BUG: cannot convert a NULL string to upper case");
  441.   for (cp = s; *cp != '\0'; cp++)
  442.     *cp = (char)toupper((int)*cp);
  443.   return s;
  444. }
  445. #endif /* QEU_DOS */
  446.  
  447.  
  448. /*
  449.  * Convert numbers depending on endianness.
  450.  */
  451. #ifdef FAT_ENDIAN
  452. UInt16 SwapInt16(UInt16 x)
  453. {
  454.   return ((x<<8) & 0xff00) | ((x>>8) & 0x00ff);
  455. }
  456.  
  457.  
  458. UInt32 SwapInt32(UInt32 x)
  459. {
  460.   return (((x << 24) & 0xff000000)
  461.           | ((x<< 8) & 0x00ff0000)
  462.           | ((x>> 8) & 0x0000ff00)
  463.           | ((x>>24) & 0x000000ff));
  464. }
  465.  
  466.  
  467. Float32 SwapFloat32(Float32 x)
  468. {
  469.   UInt32 i;
  470.   i = SwapInt32(*((UInt32 *)&x));
  471.   return *((Float32 *)&i);
  472. }
  473. #endif /* FAT_ENDIAN */
  474.  
  475. /* end of file */
  476.